/**
 * @file PLoadLib.c
 *
 * Downloads an image to Propeller using Windows32 API.
 * Ya, it's been done before, but some programs like Propellent and
 * PropTool do not recognize virtual serial ports. Hence, this program.
 *
 * Copyright (c) 2009 by John Steven Denson
 * Modified in 2011 by David Michael Betz
 *
 * MIT License                                                           
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 */

#if defined(__cplusplus)
extern "C" {
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>

#include "PLoadLib.h"
#include "PLoadLib_os.h"

#define PORTLEN 80

static char *shortFileName(char *file)
{
    while(strchr(file, '/')) {
        file = strchr(file,'/')+1;
    }
    while(strchr(file, '\\')) {
        file = strchr(file,'\\')+1;
    }
    return file;
}

static int autoport(const char *port, void *data)
{
    char *actualport = (char*)data;
    strcpy(actualport, port);
    //printf("Fount Port: %s\n", port);
    return 0;
}

int main(int argc, char *argv[])
{
    int  n  =  0;
    int  rc =  0;
    int  cat=  1;

    int  operation = DOWNLOAD_RUN_BINARY;
    char *file = 0;  // file name to load
    char port[PORTLEN+1];  // port name to load

#ifdef MINGW
    char *portprefix = "COM";
#else
    char *portprefix = "/dev/ttyUSB";
#endif

    char *progname = shortFileName(argv[0]);

    if (argc < 2) {
        printf("Usage: %s [-pName] [-r] [-e] <filename>\n", progname);
        printf("-p port name or number. Name like ");
#ifdef MINGW
        printf("COM20\n");
#else
        printf("/dev/ttyUSB0\n");
#endif
        printf("-r to load RAM (default).\n");
        printf("-e to load EEPROM.\n");
        printf("-q no terminal output.\n");
        printf("-v verbose output.\n");
        rc = -1;
    }
    else {
        *port = '\0'; // if not assigned below, do autoport.
        psetverbose(0);
        for(n = 1; n < argc; n++) {
            switch(argv[n][0]) {
                case '-':
                    switch(argv[n][1]) {
                        case 'q':
                            cat = 0;
                            break;
                        case 'r':
                            // always run
                            break;
                        case 'e':
                            operation = DOWNLOAD_RUN_EEPROM;
                            break;
                        case 'p':
#ifndef MACOSX
                            if(isdigit(argv[n][2])) {
                                snprintf(port,PORTLEN,"%s%s",portprefix,&argv[n][2]);
                            }
                            else
#endif
                                snprintf(port,PORTLEN,&argv[n][2]);
                            break;
                        case 'v':
                            psetverbose(1);
                            break;
                        default:
                            break;
                    }
                    break;

                default:
                    file = argv[n];
                    break;
            }
        }
        if(file == 0) {
            printf("Please specify a file to load.\n");
            rc = -1;
        }
        else {
            FILE *fp = fopen(file,"rb");
            int fpok = (int)fp;
            fclose(fp);

            if(!*port) {
                if(serial_find(NULL,autoport,&port)) {
                    *port = '\0';
                }
            }

            if(!fpok) {
                printf("Can't open file: %s\n", file);
                rc = -1;
            }
            else if(!*port) {
                printf("Serial port not found.\n");
                rc = -1;
            }
            else if(popenport(port, 115200)) {
                printf("Error opening serial port.\n");
                rc = -1;
            }
            else if (pload(file, operation) != 0) {
                printf("Load failed\n");
                rc = -1;
            }
            else if(cat) {
                uint8_t buf[20];
                int count = 0;
                count = rx_timeout(buf, 1, 300);
                if(count != SERIAL_TIMEOUT) {
                    puts("RECEIVED");
                }
                while(count != SERIAL_TIMEOUT) {
                    fputc(*buf,stdout);
                    count = rx_timeout(buf, 1, 300);
                }
                fflush(stdout);
                serial_done();
            }
        }
    }
    return rc;
}

#if defined(__cplusplus)
}
#endif
